package cate.game.train.kitchenware;

import cate.common.table.d.GDObj;
import cate.common.table.item.kitchenware.row.KitchenwareBaseRow;
import cate.common.table.item.kitchenware.row.KitchenwareLevelUpRow;
import cate.common.util.GameResult;
import cate.game.client.msg.MergeMsgSender;
import cate.game.event.RoleEventPublisher;
import cate.game.event.hero.HeroPowerChangeEvent;
import cate.game.res.MixRes;
import cate.game.res.MixResItem;
import cate.game.res.RewardShow;
import cate.game.role.Role;
import cate.game.role.bag.hero.Hero;
import cate.game.role.bag.kitchenware.Kitchenware;
import cate.game.train.kitchenware.msg.KitchenwareUpdateResp;
import easy.java.practice.errorcode.EcResult;
import org.apache.commons.lang3.StringUtils;

import java.util.Set;

public class TrainKitchenwareHandler implements RoleEventPublisher {
    private Kitchenware findKitchenware(Role role, String kitchenwareUid, String heroUid, byte pos) {
        if (StringUtils.isNotBlank(heroUid)) {
            Hero hero = getHero(role, heroUid);
            if(hero != null){
                Kitchenware kitchenware = hero.kitchenwaresOn.kitchenwareMap.get(pos);
                if (StringUtils.equals(kitchenwareUid, kitchenware.uid)) {
                    return kitchenware;
                }
            }
        } else {
            return role.getBag().kitchenware.getItem(kitchenwareUid);
        }
        return null;
    }

    private Hero getHero(Role role, String heroUid) {
        return role.getBag().hero.getItem(heroUid);
    }

    public GameResult<Void> levelUp(Role role, String kitchenwareUid, String heroUid, byte pos, boolean useItem) {
        GameResult<Void> r = new GameResult<>();
        Kitchenware kitchenware = findKitchenware(role, kitchenwareUid, heroUid, pos);
        if (kitchenware == null) {
            return r.fail("厨具不存在");
        }
        KitchenwareLevelUpRow levelUpRow = kitchenware.findLevelUpRow(role.getGame());
        if (levelUpRow == null) {
            return r.fail("厨具无法升级");
        }
        if (StringUtils.isBlank(levelUpRow.levelUpCostStr)) {
            return r.fail("厨具已经满级");
        }
        MixRes consume = new MixRes(levelUpRow.levelUpCostStr);
        if (useItem) {
            consume.addList(new MixRes(levelUpRow.defendLostLevelCostStr));
        }
        GameResult<MixResItem> consumeRes = consume.consume(role);
        if (!consumeRes.ok()) {
            role.getGame().notice.tipResItem(role, consumeRes.data);
            return r.fail(consumeRes);
        }
        double rate = levelUpRow.successRate / 10000;
        if (Math.random() <= rate) {
            kitchenware.levelUp(role.getGame());
            role.getGame().notice.message(role, "升级成功");
        } else {
            if (!useItem && levelUpRow.failLostLevel > 0) {
                kitchenware.levelLose(levelUpRow.failLostLevel);
            }
            role.getGame().notice.message(role, "升级失败");
        }
        onUpdatePower(role, heroUid);
        role.sendNow(new KitchenwareUpdateResp(kitchenware, heroUid, pos));
        return r;
    }

    public GameResult<Void> recast(Role role, String kitchenwareUid, String heroUid, byte pos, byte type) {
        GameResult<Void> r = new GameResult<>();
        if (type != 1 && type != 2) {
            return r.fail("错误的重铸类型");
        }
        if (type == 1) {
            return recastAttr(role, kitchenwareUid, heroUid, pos);
        } else {
            return recastSkill(role, kitchenwareUid, heroUid, pos);
        }
    }

    private GameResult<Void> recastSkill(Role role, String kitchenwareUid, String heroUid, byte pos) {
        GameResult<Void> r = new GameResult<>();
        Kitchenware kitchenware = findKitchenware(role, kitchenwareUid, heroUid, pos);
        if (kitchenware == null) {
            return r.fail("厨具不存在");
        }
        KitchenwareLevelUpRow levelUpRow = kitchenware.findMaxLevelUpRow(role.getGame());
        if (levelUpRow == null) {
            return r.fail("厨具不存在");
        }
        if (StringUtils.isBlank(levelUpRow.skillRecastCostStr)) {
            return r.fail("该厨具不可重铸技能");
        }
        GameResult<MixResItem> consumeRes = new MixRes(levelUpRow.skillRecastCostStr).consume(role);
        if (!consumeRes.ok()) {
            return r.fail(consumeRes);
        }
        kitchenware.recastSkill(role.getGame());
        role.sendNow(new KitchenwareUpdateResp(kitchenware, heroUid, pos));
        role.getGame().notice.message(role, "厨具重铸成功");
        return r;
    }

    private GameResult<Void> recastAttr(Role role, String kitchenwareUid, String heroUid, byte pos) {
        GameResult<Void> r = new GameResult<>();
        Kitchenware kitchenware = findKitchenware(role, kitchenwareUid, heroUid, pos);
        if (kitchenware == null) {
            return r.fail("厨具不存在");
        }
        KitchenwareLevelUpRow levelUpRow = kitchenware.findMaxLevelUpRow(role.getGame());
        if (levelUpRow == null) {
            return r.fail("厨具不存在");
        }
        if (StringUtils.isBlank(levelUpRow.attrRecastCostStr)) {
            return r.fail("该厨具不可重铸属性");
        }
        GameResult<MixResItem> consumeRes = new MixRes(levelUpRow.attrRecastCostStr).consume(role);
        if (!consumeRes.ok()) {
            return r.fail(consumeRes);
        }
        kitchenware.recastAttrs(role.getGame());
        role.sendNow(new KitchenwareUpdateResp(kitchenware, heroUid, pos));
        role.getGame().notice.message(role, "厨具重铸成功");
        return r;
    }

    /** 玺印重铸保存 */
    public GameResult<Void> recastSave(Role role, String kitchenwareUid, String heroUid, byte pos, byte type) {
        GameResult<Void> r = new GameResult<>();
        if (type != 1 && type != 2) {
            return r.fail("错误的重铸类型");
        }
        Kitchenware kitchenware = findKitchenware(role, kitchenwareUid, heroUid, pos);
        if (kitchenware == null) {
            return r.fail("厨具不存在");
        }
        if (type == 1) {
            kitchenware.saveTempAttr();
        } else {
            kitchenware.saveTempSkill();
        }
        role.sendNow(new KitchenwareUpdateResp(kitchenware, heroUid, pos));
        role.getGame().notice.message(role, "重铸保存成功");
        onUpdatePower(role, heroUid);
        return r.success();
    }

    /**
     * 玺印突破
     *
     * <p>用3个龙雀印合成一个真龙印 保留原来的技能 属性进行升级
     */
    public GameResult<Void> kitchenwareBreak(Role role, String kitchenwareUid, String heroUid, byte pos, Set<String> kitchenwareList) {
        GameResult<Void> r = new GameResult<>();
        if (kitchenwareList == null) {
            return r.fail("厨具突破材料选择有误");
        }
        // 突破时选择的符文本体 需要保留原来的技能
        Kitchenware kitchenware = findKitchenware(role, kitchenwareUid, heroUid, pos);
        if (kitchenware == null) {
            return r.fail("厨具突破材料选择有误");
        }
        KitchenwareBaseRow kitchenwareBaseRow = kitchenware.getTpl(role.getGame());
        if (kitchenwareBaseRow == null) {
            return r.fail("突破的厨具选择有误");
        }
        if (kitchenwareBaseRow.breakCostNum == 0) {
            return r.fail("该厨具无法突破");
        }
        if (kitchenwareBaseRow.breakCostNum != kitchenwareList.size() || kitchenwareList.contains(kitchenwareUid)) {
            return r.fail("厨具突破材料选择有误");
        }
        r = beakAvaible(role, kitchenware, kitchenwareBaseRow);
        if (!r.ok()) {
            return r;
        }
        // 检测用于消耗的材料是否满足条件
        for (String s : kitchenwareList) {
            Kitchenware cost = role.getBag().kitchenware.getItem(s);
            r = beakAvaible(role, cost, kitchenwareBaseRow);
            if (!r.ok()) {
                return r;
            }
        }
        // 扣除突破的资源
        EcResult<MixResItem> consumeRes = new MixRes(kitchenwareBaseRow.breakCostStr).consume(role, null);
        if (!consumeRes.ok()) {
            role.getGame().notice.tipResItem(role, consumeRes.data);
            return r.fail(consumeRes);
        }
        for (String s : kitchenwareList) {
            role.getBag().kitchenware.removeItem(s, null);
        }
        kitchenware.breakUp(role.getGame(), kitchenwareBaseRow.breakTid);
        role.sendNow(new KitchenwareUpdateResp(kitchenware, heroUid, pos));

        RewardShow rewardShow = new RewardShow();
        rewardShow.addBagInstance(kitchenware);
        role.getGame().notice.dialog(role, rewardShow);
        onUpdatePower(role, heroUid);
        return r.success();
    }

    /** 玺印分解 */
    public void decompose(Role role, Set<String> kitchenwareUids) {
        if(kitchenwareUids == null || kitchenwareUids.isEmpty()){
            role.getGame().notice.message(role, "厨具不可为空");
            return;
        }
        MixRes reward = new MixRes();
        MergeMsgSender sender = new MergeMsgSender();
        for(String runeUid : kitchenwareUids){
            Kitchenware kitchenware = role.getBag().kitchenware.getItem(runeUid);
            if (kitchenware == null) {
                role.getGame().notice.message(role, "厨具不存在");
                continue;
            }
            // 如果没有配置分解奖励 就默认为不能分解
            KitchenwareLevelUpRow levelUpRow = kitchenware.findMaxLevelUpRow(role.getGame());
            if (levelUpRow == null || StringUtils.isBlank(levelUpRow.decomposeRewardStr)) {
                role.getGame().notice.message(role, "该厨具不可分解");
                continue;
            }
            MixRes treward = new MixRes(levelUpRow.decomposeRewardStr);
            GameResult<Void> r = treward.addCheck(role);
            if (!r.ok()) {
                role.getGame().notice.message(role, r.message);
                continue;
            }
            role.getBag().kitchenware.removeItem(runeUid, sender);
            reward.addList(treward);
        }
        sender.send(role, true);
        reward.addAndDialog(role, true, 0);
    }

    private GameResult<Void> beakAvaible(Role role, Kitchenware cost, KitchenwareBaseRow limitRow) {
        GameResult<Void> r = new GameResult<>();
        if (cost == null) {
            return r.fail("消耗的厨具不存在");
        }
        KitchenwareBaseRow costRow = cost.getTpl(role.getGame());
        if (costRow == null) {
            return r.fail("消耗的厨具不存在");
        }
        if (costRow.quality != limitRow.quality || costRow.pos != limitRow.pos || costRow.star != limitRow.star) {
            return r.fail("厨具突破材料选择有误");
        }
        return r.success();
    }

    private void onUpdatePower(Role role, String heroUid) {
        if (StringUtils.isNotBlank(heroUid)) {
            publishEvent(role, new HeroPowerChangeEvent(role, role.getBag().hero.getItem(heroUid)));
            role.getBase().updatePower();
        }
    }
}
